package lol.clann.bukkit.pluginboot.util;

import lol.clann.bukkit.pluginboot.version.VersionSetup;
import lol.clann.clannboot.annotation.inject.Inject;
import lol.clann.clannboot.annotation.svc.PostInstance;
import lol.clann.clannboot.annotation.svc.Service;
import lol.clann.clannboot.util.clazz.ClassUtils;
import lol.clann.clannboot.util.clazz.MethodCondition;
import lol.clann.clannboot.util.clazz.WrapClass;
import lol.clann.clannboot.util.clazz.WrapMethod;
import org.bukkit.Material;
import org.bukkit.block.Block;

/**
 * @author pyz
 * @date 2018/8/5 上午7:40
 */
@Service(priority = Integer.MAX_VALUE)
public class BlockUtils {

    public static final WrapClass classCraftBlock = ClassUtils.forName("{cb}.block.CraftBlock");
    public static final WrapClass classNMSBlockFluids = ClassUtils.forName("{nms}.BlockFluids");
    public static WrapClass classForgeBlockFluids;

    @Inject
    private WorldUtils worldUtils;
    @Inject
    private LocationUtils locationUtils;
    @Inject
    private TileEntityUtils tileEntityUtils;
    @Inject
    private NBTCompoundUtils nbtCompoundUtils;
    @Inject
    private InventoryUtils inventoryUtils;

    private WrapMethod getNMSBlock;

    @PostInstance
    private void init() {
        getNMSBlock = classCraftBlock.getMethod(MethodCondition.of("getNMSBlock", new Class[0]));
        if (VersionSetup.isForge()) {
            classForgeBlockFluids = ClassUtils.forName("net.minecraftforge.fluids.BlockFluidBase");
        }
    }

    public boolean isInventory(Block block) {
        if (isEmpty(block)) {
            return false;
        }
        Object te = worldUtils.getTileEntity(block);

        if (te != null && inventoryUtils.isNMSInventory(te)) {
            return true;
        }
        return false;
    }

    public boolean isEmpty(Block b) {
        if (b == null || b.isEmpty()) {
            return true;
        }
        return false;
    }

    public boolean isFliudBlock(Block b) {
        if (isEmpty(b)) {
            return false;
        }
        if (b.isLiquid()) {
            return true;
        }
        Object nmsBlock = getNMSBlock.invoke(b);
        if (nmsBlock == null) {
            return false;
        }
        if (classNMSBlockFluids.isInstance(nmsBlock) || (classForgeBlockFluids != null && classForgeBlockFluids.isInstance(nmsBlock))) {
            return true;
        }
        return false;
    }

    public Object toCompound(Block block) {
        Object tag = nbtCompoundUtils.newTagCompound();
        nbtCompoundUtils.setString(tag, "id", block.getType().name());
        nbtCompoundUtils.setByte(tag, "data", block.getData());
        nbtCompoundUtils.setTag(tag, "loc", locationUtils.toCompound(block.getLocation()));
        Object te = worldUtils.getTileEntity(block);
        if (te != null) {
            nbtCompoundUtils.setTag(tag, "tileentity", tileEntityUtils.toCompound(te));
        }
        return tag;
    }

//    public void fill(Block b, Object nbtTag) {
//        String id = nbtCompoundUtils.getString(nbtTag, "id");
//        b.setType(Material.getMaterial(id));
//        byte data = nbtCompoundUtils.getByte(nbtTag, "data");
//        b.setData(data);
//        Object te = nbtCompoundUtils.getTag(nbtTag, "tileentity");
//        if (te != null) {
//            Object tileEntity = worldUtils.getTileEntity(b.getWorld(), b.getX(), b.getY(), b.getZ());
//            if (tileEntity == null) {
//                tileEntity = tileEntityUtils.fromCompound(te);
//                worldUtils.addTileEntity(b.getWorld(), tileEntity);
//            } else {
//                tileEntityUtils.fill(tileEntity, te);
//            }
//        }
//    }

    public Object toNMS(Block bukkit) {
        return bukkit == null ? null : getNMSBlock.invoke(bukkit);
    }

    /**
     * @param b
     * @return NBTTagCompound(副本)
     */
    public Object getTagCompound(Block b) {
        Object te = worldUtils.getTileEntity(b);
        if (te != null) {
            return tileEntityUtils.toCompound(te);
        }
        return null;
    }
}
